package com.benchproject.aspects;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class LoggingAspect {

	protected final Log logger = LogFactory.getLog(getClass());

	/**
	 * A join point is in the service layer if the method is defined in a type
	 * in the com.benchproject.services package or any sub-package under that.
	 */
	@Pointcut("within(com.benchproject.services..*)")
	public void inServicesLayer() {
	}

	/**
	 * A join point is in the persistence layer if the method is defined in a
	 * type in the com.benchproject.persist package or any sub-package under
	 * that.
	 */
	@Pointcut("within(com.benchproject.persist..*)")
	public void inPersistLayer() {
	}

	@Around("inPersistLayer()")
	public Object logEnterAndExit(ProceedingJoinPoint pjp) throws Throwable {

		StringBuilder signature = new StringBuilder().append(
				pjp.getSignature().getDeclaringTypeName()).append(".").append(
				pjp.getSignature().getName());

		if (logger.isDebugEnabled()) {

			StringBuilder logMsg = new StringBuilder().append("Enter ").append(
					signature);

			Object[] args = pjp.getArgs();
			if (args.length > 0) {
				logMsg.append(", args: ");
				for (Object arg : args) {
					if (arg != null) {
						logMsg.append(arg.toString());
					} else {
						logMsg.append("null");
					}
					logMsg.append(", ");
				}
			}
			logger.debug(logMsg);
		}

		Object retVal = pjp.proceed();

		if (logger.isDebugEnabled()) {
			StringBuilder logMsg = new StringBuilder().append("Exit ").append(
					signature).append(", returning: ");
			if (retVal == null) {
				logMsg.append("null");
			} else {
				logMsg.append(retVal.toString());
			}
			logger.debug(logMsg);
		}

		return retVal;
	}

}
